home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / packer / lhlib / lhdecode.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  17KB  |  806 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by Holger P. Krekel & Olaf 'Olsen' Barthel
  4.  *
  5.  *    Name .....: LhDecode.c
  6.  *    Created ..: Wednesday 11-Jul-90 19:40
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    11-Jul-90       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15.     /* ARP cli template and help information. */
  16.  
  17. char *CLI_Template    = "FROM,TO,N=NoQuery/S,F=Faster/S";
  18. char *CLI_Help        = "\n\33[33m\33[1mLhDecode \33[0m\33[31m© Copyright 1990 by Holger P. Krekel & Olaf Barthel,\n\
  19.            All rights reserved.\n\n\
  20. Usage: \33[1mLhDecode\33[0m [File or wildcard pattern] [File/directory name]\n\
  21.                 [FASTER] [NOQUERY]\n";
  22.  
  23.     /* Argument vector offsets. */
  24.  
  25. #define ARG_FROM    1
  26. #define ARG_TO        2
  27. #define ARG_NOQUERY    3
  28. #define ARG_FASTER    4
  29.  
  30.     /* Global and shared data. */
  31.  
  32. struct Library        *LhBase;
  33. struct timerequest    *TimeRequest;
  34. struct MsgPort        *TimePort;
  35. struct Device        *TimerBase;
  36. struct FileRequester    *FileRequester;
  37. struct LhBuffer        *LhBuffer;
  38.  
  39. BYTE             Faster,Query = TRUE;
  40. ULONG             TotalSecs = 0,TotalMicros = 0;
  41. LONG             TotalRatio,NumEntries = 0;
  42.  
  43.     /* Linked list of file names. */
  44.  
  45. struct NameLink         *RootLink;
  46. char            **NameList;
  47. LONG              NumNames = 0;
  48.  
  49.     /* Function prototypes. */
  50.  
  51. extern int         SubCmp();
  52. LONG             StrCmp(char **Str1,char **Str2);
  53. BYTE             BuildList(VOID);
  54. VOID             FreeLinks(VOID);
  55. BYTE             ScanDir(char *Pattern);
  56. LONG             GetFileSize(char *Name);
  57. BYTE             SetRawMode(BYTE Mode);
  58. BYTE             Decode(char *Src,char *Dst);
  59. VOID             main(int argc,char **argv);
  60.  
  61.     /* Stub routines. */
  62.  
  63. LONG Chk_Abort(VOID)    { return(0); }
  64. VOID _wb_parse(VOID)    {}
  65.  
  66.     /* Assembly language fragment to be used by the QSort
  67.      * routine.
  68.      */
  69.  
  70. #asm
  71.     xdef    _SubCmp
  72.  
  73. _SubCmp:movem.l    d2-d7/a2-a6,-(sp)
  74.     movem.l    a0/a1,-(sp)
  75.  
  76.     jsr    _geta4#
  77.     jsr    _StrCmp
  78.  
  79.     add.w    #8,sp
  80.  
  81.     movem.l    (sp)+,d2-d7/a2-a6
  82.     rts
  83. #endasm
  84.  
  85.     /* StrCmp():
  86.      *
  87.      *    Compare two strings ignoring case (international).
  88.      */
  89.  
  90. LONG
  91. StrCmp(char **Str1,char **Str2)
  92. {
  93.     char *a = *Str1,*b = *Str2;
  94.  
  95.     for( ; ToUpper(*a) == ToUpper(*b) ; a++, b++)
  96.     {
  97.         if(!(*a))
  98.             return(0);
  99.     }
  100.  
  101.     return(ToUpper(*a) - ToUpper(*b));
  102. }
  103.  
  104.     /* BuildList():
  105.      *
  106.      *    Build an array of string pointers to be passed to the
  107.      *    QSort function by scanning a linked list of names.
  108.      */
  109.  
  110. BYTE
  111. BuildList()
  112. {
  113.     struct NameLink    *TempLink;
  114.  
  115.     for(TempLink = RootLink ; TempLink ; TempLink = TempLink -> Next)
  116.         NumNames++;
  117.  
  118.     if(NameList = (char **)ArpAlloc(NumNames * sizeof(char *)))
  119.     {
  120.         NumNames = 0;
  121.  
  122.         for(TempLink = RootLink ; TempLink ; TempLink = TempLink -> Next)
  123.         {
  124.             if(NameList[NumNames] = (char *)ArpAlloc(strlen(TempLink -> Name) + 1))
  125.                 strcpy(NameList[NumNames++],TempLink -> Name);
  126.             else
  127.                 return(FALSE);
  128.         }
  129.  
  130.         return(QSort(NameList,NumNames,sizeof(char *),SubCmp));
  131.     }
  132.  
  133.     return(FALSE);
  134. }
  135.  
  136.     /* FreeLinks():
  137.      *
  138.      *    Free the linked list of names created by the directory
  139.      *    scanner.
  140.      */
  141.  
  142. VOID
  143. FreeLinks()
  144. {
  145.     struct NameLink *TempLink,*LastLink = NULL;
  146.  
  147.     for(TempLink = RootLink ; TempLink ; TempLink = LastLink)
  148.     {
  149.         LastLink = TempLink -> Next;
  150.  
  151.         FreeMem(TempLink,sizeof(struct NameLink));
  152.     }
  153. }
  154.  
  155.     /* ScanDir():
  156.      *
  157.      *    Scan a directory for a given pattern and build a linked
  158.      *    list of the names.
  159.      */
  160.  
  161. BYTE
  162. ScanDir(char *Pattern)
  163. {
  164.     struct NameLink    *LastLink = NULL;
  165.     char        *Temp;
  166.  
  167.     while(Temp = scdir(Pattern))
  168.     {
  169.         if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  170.         {
  171.             SetSignal(0,SIGBREAKF_CTRL_C);
  172.  
  173.             Puts("\n*** BREAK: LhDecode\a");
  174.  
  175.             return(FALSE);
  176.         }
  177.  
  178.         if(SetSignal(0,0) & SIGBREAKF_CTRL_D)
  179.         {
  180.             SetSignal(0,SIGBREAKF_CTRL_D);
  181.             return(TRUE);
  182.         }
  183.  
  184.         if(RootLink)
  185.         {
  186.             struct NameLink *NextLink;
  187.  
  188.             if(NextLink = (struct NameLink *)AllocMem(sizeof(struct NameLink),MEMF_PUBLIC | MEMF_CLEAR))
  189.             {
  190.                 LastLink -> Next = NextLink;
  191.  
  192.                 strcpy(NextLink -> Name,Temp);
  193.  
  194.                 LastLink = NextLink;
  195.             }
  196.             else
  197.                 return(TRUE);
  198.         }
  199.         else
  200.         {
  201.             if(RootLink = (struct NameLink *)AllocMem(sizeof(struct NameLink),MEMF_PUBLIC | MEMF_CLEAR))
  202.             {
  203.                 strcpy(RootLink -> Name,Temp);
  204.  
  205.                 LastLink = RootLink;
  206.             }
  207.             else
  208.                 return(TRUE);
  209.         }
  210.     }
  211.  
  212.     return(TRUE);
  213. }
  214.  
  215.     /* GetFileSize():
  216.      *
  217.      *    Asks the DOS to return the length of a given file.
  218.      */
  219.  
  220. LONG
  221. GetFileSize(char *Name)
  222. {
  223.     struct FileInfoBlock    *FileInfo;
  224.     BPTR             FileLock;
  225.     LONG             FileSize = 0;
  226.  
  227.     if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  228.     {
  229.         if(FileLock = Lock(Name,ACCESS_READ))
  230.         {
  231.             if(Examine(FileLock,FileInfo))
  232.                 FileSize = FileInfo -> fib_Size;
  233.  
  234.             UnLock(FileLock);
  235.         }
  236.  
  237.         FreeMem(FileInfo,sizeof(struct FileInfoBlock));
  238.     }
  239.  
  240.     return(FileSize);
  241. }
  242.  
  243.     /* SetRawMode():
  244.      *
  245.      *    Toggles between raw (single character) and 'cooked'
  246.      *    (line input) data input from a console window.
  247.      */
  248.  
  249. BYTE
  250. SetRawMode(BYTE Mode)
  251. {
  252.     LONG Args[7];
  253.  
  254.     if(Mode)
  255.         Args[0] = DOSTRUE;
  256.     else
  257.         Args[0] = DOSFALSE;
  258.  
  259.     return(SendPacket(ACTION_SCREEN_MODE,Args,(struct MsgPort *)((struct Process *)SysBase -> ThisTask) -> pr_ConsoleTask));
  260. }
  261.  
  262.     /* Decode():
  263.      *
  264.      *    Decode a file previously run through LhEncode.
  265.      */
  266.  
  267. BYTE
  268. Decode(char *Src,char *Dst)
  269. {
  270.     BPTR         In,Out;
  271.     ULONG         FromSize,ToSize;
  272.     LONG        *From,*To;
  273.  
  274.     LONG         Secs,Micros;
  275.     BYTE         Ratio;
  276.  
  277.     struct timeval     Req1,Req2;
  278.  
  279.     char         TempName[MaxInputBuf];
  280.     BPTR         CheckLock;
  281.  
  282.     Printf("%-31.31s ",BaseName(Src));
  283.  
  284.         /* How long is our source file? */
  285.  
  286.     if(!(FromSize = GetFileSize(Src)))
  287.     {
  288.         Printf("\33[33munable to examine file (Error %ld)\33[31m\a\n",IoErr());
  289.         return(TRUE);
  290.     }
  291.  
  292.         /* Subtract leading size identifier. */
  293.  
  294.     FromSize -= sizeof(LONG);
  295.  
  296.     if(!(From = AllocMem(FromSize,MEMF_PUBLIC)))
  297.     {
  298.         Printf("\33[33mout of memory (Error 103)\33[31m\a\n");
  299.         return(TRUE);
  300.     }
  301.  
  302.         /* Open the file for reading. */
  303.  
  304.     if(!(In = Open(Src,MODE_OLDFILE)))
  305.     {
  306.         FreeMem(From,FromSize);
  307.  
  308.         Printf("\33[33munable to open file (Error %ld)\33[31m\a\n",IoErr());
  309.         return(TRUE);
  310.     }
  311.  
  312.         /* Read the size ID (size of original file). */
  313.  
  314.     if(Read(In,&ToSize,sizeof(ULONG)) != sizeof(ULONG))
  315.     {
  316.         LONG Error = IoErr();
  317.  
  318.         Close(In);
  319.  
  320.         FreeMem(From,FromSize);
  321.  
  322.         Printf("\33[33munable to read file (Error %ld)\33[31m\a\n",Error);
  323.         return(TRUE);
  324.     }
  325.  
  326.         /* Mask out the 'special' LhEncode identifier. If the
  327.          * upmost byte equals to ~0 the file is supposed to be
  328.          * valid.
  329.          */
  330.  
  331.     if((ToSize & 0xFF000000) != 0xFF000000)
  332.     {
  333.         Close(In);
  334.  
  335.         FreeMem(From,FromSize);
  336.  
  337.         Printf("\33[33mfile is not encoded (Error 212)\33[31m\a\n");
  338.         return(TRUE);
  339.     }
  340.     else
  341.         ToSize &= 0x00FFFFFF;
  342.  
  343.         /* Read the encoded data. */
  344.  
  345.     if(Read(In,From,FromSize) != FromSize)
  346.     {
  347.         LONG Error = IoErr();
  348.  
  349.         Close(In);
  350.  
  351.         FreeMem(From,FromSize);
  352.  
  353.         Printf("\33[33munable to read file (Error %ld)\33[31m\a\n",Error);
  354.         return(TRUE);
  355.     }
  356.  
  357.     Close(In);
  358.  
  359.         /* Allocate the destination buffer. */
  360.  
  361.     if(!(To = AllocMem(ToSize,MEMF_PUBLIC | MEMF_CLEAR)))
  362.     {
  363.         FreeMem(From,FromSize);
  364.  
  365.         Printf("\33[33mout of memory (Error 103)\33[31m\a\n");
  366.         return(TRUE);
  367.     }
  368.  
  369.         /* Initialize the LhBuffer. */
  370.  
  371.     LhBuffer -> lh_Src    = From;
  372.     LhBuffer -> lh_Dst    = To;
  373.  
  374.     Printf("\33[33m%07ld\33[31m Decode ",FromSize);
  375.  
  376.         /* If 'faster' encoding selected, disable interrupts
  377.          * and system DMA.
  378.          */
  379.  
  380.     if(Faster)
  381.     {
  382.         custom . dmacon = BITCLR | DMAF_ALL;
  383.         Disable();
  384.         custom . color[0] = 0;
  385.     }
  386.  
  387.         /* Remember starting time. */
  388.  
  389.     DoIO(TimeRequest);
  390.  
  391.     Req1 = TimeRequest -> tr_time;
  392.  
  393.         /* Decode the data. */
  394.  
  395.     LhDecode(LhBuffer);
  396.  
  397.         /* Remember finishing time. */
  398.  
  399.     DoIO(TimeRequest);
  400.  
  401.     Req2 = TimeRequest -> tr_time;
  402.  
  403.         /* Reenable DMA and interrupts. */
  404.  
  405.     if(Faster)
  406.     {
  407.         custom . dmacon = BITSET | DMAF_ALL;
  408.         Enable();
  409.     }
  410.  
  411.         /* Subtract both time values. */
  412.  
  413.     SubTime(&Req2,&Req1);
  414.  
  415.         /* Calculate time and compression ration. */
  416.  
  417.     Secs    = Req2 . tv_secs;
  418.     Micros    = Req2 . tv_micro / 10000;
  419.  
  420.     Ratio    = 100 - (100 * FromSize) / ToSize;
  421.  
  422.         /* Add them for the statistics. */
  423.  
  424.     TotalSecs    += Secs;
  425.     TotalMicros    += Micros;
  426.  
  427.     Printf("\33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  428.  
  429.         /* ^C pressed = abort. */
  430.  
  431.     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  432.     {
  433.         FreeMem(From,FromSize);
  434.         FreeMem(To,ToSize);
  435.  
  436.         SetSignal(0,SIGBREAKF_CTRL_C);
  437.         Puts("\n*** BREAK: LhDecode\a");
  438.         return(FALSE);
  439.     }
  440.  
  441.         /* Check if we are about to overwrite an existing file. */
  442.  
  443.     if(Query)
  444.     {
  445.         if(CheckLock = Lock(Dst,ACCESS_READ))
  446.         {
  447.             UnLock(CheckLock);
  448.  
  449.             SetRawMode(TRUE);
  450.  
  451.             Printf("\2331A\n\23332C\233KOverwrite (\33[33mN\33[31mo/\33[33mY\33[31mes/\33[33mC\33[31mhange) ? ");
  452.  
  453.                 /* Read a character. */
  454.  
  455. Ask:            if(Read(((struct Process *)SysBase -> ThisTask) -> pr_CIS,TempName,1) > 0)
  456.             {
  457.                 if(toupper(TempName[0]) == 'Y')
  458.                 {
  459.                     Printf("\2331A\n\23332C\233K\33[33m%07ld\33[31m Encode \33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",FromSize,(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  460.  
  461.                     SetRawMode(FALSE);
  462.  
  463.                     goto GoOn;
  464.                 }
  465.  
  466.                 if(toupper(TempName[0]) == 'N' || !TempName[0] || TempName[0] == '\n')
  467.                     goto Nope;
  468.  
  469.                 if(toupper(TempName[0]) != 'C')
  470.                     goto Ask;
  471.  
  472.                     /* Ask for a new name to save the file
  473.                      * under.
  474.                      */
  475.  
  476.                 Printf("\2331A\n\233KNew Name: %s\2331A\n\23310C",Dst);
  477.  
  478.                 SetRawMode(FALSE);
  479.  
  480.                 ReadLine(TempName);
  481.  
  482.                 if(!TempName[0] || TempName[0] == '\n')
  483.                 {
  484.                     strcpy(TempName,Dst);
  485.                     Printf("\2331A\233K");
  486.                 }
  487.  
  488.                 Dst = TempName;
  489.  
  490.                 Printf("\2331A\n\233K%-31.31s \33[33m%07ld\33[31m Encode \33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",BaseName(Dst),FromSize,(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  491.  
  492.                 goto GoOn;
  493.             }
  494.  
  495.                 /* Free the buffers and return. */
  496.  
  497. Nope:            FreeMem(From,FromSize);
  498.             FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  499.  
  500.             Printf("\2331A\n\23332C\33[1m\233KSkipped\33[0m\n");
  501.  
  502.             SetRawMode(FALSE);
  503.  
  504.             return(TRUE);
  505.         }
  506.     }
  507.  
  508.         /* Open the output file. */
  509.  
  510. GoOn:    if(!(Out = Open(Dst,MODE_NEWFILE)))
  511.     {
  512.         FreeMem(From,FromSize);
  513.         FreeMem(To,ToSize);
  514.  
  515.         Printf("\33[33m\nERROR:\33[31m Unable to open file (Error %ld)\a\n",IoErr());
  516.  
  517.         return(TRUE);
  518.     }
  519.  
  520.         /* Write the file to disk. */
  521.  
  522.     if(Write(Out,To,ToSize) != ToSize)
  523.     {
  524.         LONG Error = IoErr();
  525.  
  526.         Close(Out);
  527.  
  528.         FreeMem(From,FromSize);
  529.         FreeMem(To,ToSize);
  530.  
  531.         Printf("\33[33m\nERROR:\33[31m Unable to save file (Error %ld)\a\n",Error);
  532.  
  533.         DeleteFile(Dst);
  534.  
  535.         return(TRUE);
  536.     }
  537.  
  538.     Close(Out);
  539.  
  540.         /* Free the buffers and return. That was pretty painless,
  541.          * wasn't it?
  542.          */
  543.  
  544.     FreeMem(From,FromSize);
  545.     FreeMem(To,ToSize);
  546.  
  547.     Printf("\33[33m%07ld\33[31m Done.\n",ToSize);
  548.  
  549.     return(TRUE);
  550. }
  551.  
  552. VOID
  553. main(int argc,char **argv)
  554. {
  555.     char Match[DSIZE],TempName[DSIZE * 5 + FCHARS],TempName2[DSIZE * 5 + FCHARS],TempName3[DSIZE * 5 + FCHARS],*ToFile;
  556.     BYTE Success = RETURN_FAIL;
  557.  
  558.     if(!argc)
  559.         exit(-1);
  560.  
  561.     Enable_Abort = FALSE;
  562.  
  563.         /* Faster decompression? */
  564.  
  565.     if(argv[ARG_FASTER])
  566.         Faster = TRUE;
  567.     else
  568.         Faster = FALSE;
  569.  
  570.         /* Don't ask before overwriting a file? */
  571.  
  572.     if(argv[ARG_NOQUERY])
  573.         Query = FALSE;
  574.  
  575.         /* If the destination argument is omitted, we'll assume
  576.          * that we will decompress into the current directory.
  577.          */
  578.  
  579.     if(argv[ARG_TO])
  580.         ToFile = argv[ARG_TO];
  581.     else
  582.     {
  583.         if(PathName(((struct Process *)SysBase -> ThisTask) -> pr_CurrentDir,TempName3,DSIZE * 5))
  584.             ToFile = TempName3;
  585.         else
  586.         {
  587.             Puts("\33[1mLhEncode:\33[0m Destination file/directory name required.\a");
  588.             exit(RETURN_ERROR);
  589.         }
  590.     }
  591.  
  592.     Puts("\n\33[33m\33[1mLhDecode \33[0m\33[31m© Copyright 1990 by Holger P. Krekel & Olaf Barthel,\n           All rights reserved.\n");
  593.  
  594.         /* Open lh.library (most important call in this program). */
  595.  
  596.     if(LhBase = (struct Library *)ArpOpenLibrary(LH_NAME,LH_VERSION))
  597.     {
  598.             /* Create an LhBuffer for data decompression only. */
  599.  
  600.         if(LhBuffer = (struct LhBuffer *)CreateBuffer(TRUE))
  601.         {
  602.             if(FileRequester = ArpAllocFreq())
  603.             {
  604.                 if(TimePort = CreatePort(NULL,0))
  605.                 {
  606.                     if(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest)))
  607.                     {
  608.                             /* Open the timer.device, we will need it for
  609.                              * stopwatch functions.
  610.                              */
  611.  
  612.                         if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  613.                         {
  614.                             TimerBase = TimeRequest -> tr_node . io_Device;
  615.  
  616.                             TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  617.  
  618.                                 /* We got a source argument, no need to call the
  619.                                  * ARP file requester.
  620.                                  */
  621.  
  622.                             if(argv[ARG_FROM])
  623.                             {
  624.                                 if(ToFile)
  625.                                 {
  626.                                     struct FileInfoBlock    *FileInfo;
  627.                                     BPTR             FileLock;
  628.                                     BYTE             IsDir = FALSE,GotIt = FALSE,IsWild;
  629.  
  630.                                         /* Check if destination is a file or
  631.                                          * a directory.
  632.                                          */
  633.  
  634.                                     if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  635.                                     {
  636.                                         if(FileLock = Lock(ToFile,ACCESS_READ))
  637.                                         {
  638.                                             GotIt = TRUE;
  639.  
  640.                                             if(Examine(FileLock,FileInfo))
  641.                                                 IsDir = (FileInfo -> fib_DirEntryType > 0);
  642.  
  643.                                             UnLock(FileLock);
  644.                                         }
  645.  
  646.                                         FreeMem(FileInfo,sizeof(struct FileInfoBlock));
  647.                                     }
  648.  
  649.                                         /* Check if source is a plain file name
  650.                                          * or a wildcard expression.
  651.                                          */
  652.  
  653.                                     IsWild = PreParse(argv[ARG_FROM],Match);
  654.  
  655.                                         /* Strange... */
  656.  
  657.                                     if(IsWild && !GotIt)
  658.                                     {
  659.                                         Puts("\33[1mLhDecode:\33[0m Unable to find destination directory!\a");
  660.                                         goto Quit;
  661.                                     }
  662.  
  663.                                         /* Send a bunch of files to a single file? */
  664.  
  665.                                     if(IsWild && !IsDir)
  666.                                     {
  667.                                         Puts("\33[1mLhDecode:\33[0m Destination is not a directory!\a");
  668.                                         goto Quit;
  669.                                     }
  670.  
  671.                                         /* Source is a plain file. */
  672.  
  673.                                     if(!IsWild)
  674.                                     {
  675.                                         Puts("\33[33mDecoding\33[31m - press \33[1mCTRL-C\33[0m to abort.\n");
  676.  
  677.                                         Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  678.  
  679.                                         strcpy(TempName,ToFile);
  680.  
  681.                                         if(IsDir)
  682.                                             TackOn(TempName,BaseName(argv[ARG_FROM]));
  683.  
  684.                                         if(Decode(argv[ARG_FROM],TempName))
  685.                                             Success = RETURN_OK;
  686.                                     }
  687.                                     else
  688.                                     {
  689.                                         LONG i;
  690.  
  691.                                         Success = RETURN_OK;
  692.  
  693.                                             /* Source is a wildcard expression,
  694.                                              * start the directory scanner.
  695.                                              */
  696.  
  697.                                         Printf("\33[33mScanning\33[31m - press \33[1mCTRL-D\33[0m to stop, \33[1mCTRL-C\33[0m to abort... ");
  698.  
  699.                                         if(!ScanDir(argv[ARG_FROM]))
  700.                                             exit(RETURN_WARN);
  701.  
  702.                                         Printf("Sorting\n");
  703.  
  704.                                             /* Convert the linked list and sort
  705.                                              * it.
  706.                                              */
  707.  
  708.                                         BuildList();
  709.  
  710.                                         Puts("\2331A\233K\33[33mDecoding\33[31m - press \33[1mCTRL-C\33[0m to abort.\n");
  711.  
  712.                                         Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  713.  
  714.                                         for(i = 0 ; i < NumNames ; i++)
  715.                                         {
  716.                                             strcpy(TempName,ToFile);
  717.  
  718.                                             if(IsDir)
  719.                                                 TackOn(TempName,BaseName(NameList[i]));
  720.  
  721.                                             if(!Decode(NameList[i],TempName))
  722.                                             {
  723.                                                 Success = RETURN_FAIL;
  724.                                                 break;
  725.                                             }
  726.                                         }
  727.  
  728.                                         FreeLinks();
  729.  
  730.                                         if(!Success)
  731.                                         {
  732.                                             TotalSecs    += TotalMicros / 100;
  733.                                             TotalMicros    %= 100;
  734.  
  735.                                             Printf("\n\33[33mTotal Time\33[31m %02ld:%02ld:%02ld\n",TotalSecs / 60,TotalSecs % 60,TotalMicros);
  736.                                         }
  737.                                     }
  738.  
  739.                                     Puts("");
  740.                                 }
  741.                                 else
  742.                                     Puts("\33[1mLhDecode:\33[0m Destination file/directory name required.\a");
  743.                             }
  744.                             else
  745.                             {
  746.                                 Success = RETURN_OK;
  747.  
  748.                                 Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  749.  
  750.                                     /* We didn't get a source file and a destination directory,
  751.                                      * so let's bring up the ARP file requester.
  752.                                      */
  753.  
  754.                                 for(;;)
  755.                                 {
  756.                                     FileRequester -> fr_Hail = "Select file to decode";
  757.  
  758.                                     FileRequester -> fr_File[0] = 0;
  759.  
  760.                                     if(!FileRequest(FileRequester))
  761.                                         break;
  762.  
  763.                                     strcpy(TempName,FileRequester -> fr_Dir);
  764.                                     TackOn(TempName,FileRequester -> fr_File);
  765.  
  766.                                     strcpy(FileRequester -> fr_File,"Directories only!");
  767.  
  768.                                     FileRequester -> fr_Hail = "Select destination directory";
  769.  
  770.                                     if(!FileRequest(FileRequester))
  771.                                         break;
  772.  
  773.                                     strcpy(TempName2,FileRequester -> fr_Dir);
  774.                                     TackOn(TempName2,BaseName(TempName));
  775.  
  776.                                     Decode(TempName,TempName2);
  777.                                 }
  778.                             }
  779.  
  780. Quit:                            CloseDevice(TimeRequest);
  781.                         }
  782.                         else
  783.                             Puts("\33[1mLhDecode:\33[0m Unable to open timer.device!\a");
  784.  
  785.                         DeleteExtIO(TimeRequest);
  786.                     }
  787.                     else
  788.                         Puts("\33[1mLhDecode:\33[0m Out of memory!\a");
  789.  
  790.                     DeletePort(TimePort);
  791.                 }
  792.                 else
  793.                     Puts("\33[1mLhDecode:\33[0m Unable to create MsgPort!\a");
  794.             }
  795.             else
  796.                 Puts("\33[1mLhDecode:\33[0m Unable to allocate Arp Filerequester!\a");
  797.         }
  798.         else
  799.             Puts("\33[1mLhDecode:\33[0m Out of memory!\a");
  800.     }
  801.     else
  802.         Printf("\33[1mLhDecode:\33[0m You need \"%s\" V%ld.0 or higher!\a\n",LH_NAME,LH_VERSION);
  803.  
  804.     exit(Success);
  805. }
  806.